package com.atguigu.juc.threadLocal;

import java.lang.ref.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author yfstart
 * @create 2022-07-25 18:18
 */
public class ReferenceDemo {
    public static void main(String[] args) {
        // strongReference();
        // softReference();
        // weakReference();
        phantomReference();
    }

    private static void phantomReference() {
        MyObject myObject = new MyObject();
        ReferenceQueue<MyObject> referenceQueue = new ReferenceQueue<>();
        PhantomReference phantomReference = new PhantomReference(myObject, referenceQueue);

        List<byte[]> list = new ArrayList<>();

        new Thread(() -> {
            while (true){
                list.add(new byte[1 * 1024 * 1024]);
                try { TimeUnit.MILLISECONDS.sleep(1000); } catch (InterruptedException e) { e.printStackTrace();}
                System.out.println(phantomReference.get() + "\t list add ok");
            }
        }, "t1").start();

        new Thread(() -> {
            while (true){
                Reference<? extends MyObject> poll = referenceQueue.poll();
                if (poll != null){
                    System.out.println("有虚对象加入了队列");
                    break;
                }
            }
        }, "t2").start();

    }

    private static void weakReference() {
        WeakReference<MyObject> weakReference = new WeakReference<>(new MyObject());
        System.out.println("gc after：" + weakReference.get() + "\t内存够用");
        System.gc();
        try { TimeUnit.MILLISECONDS.sleep(1000); } catch (InterruptedException e) { e.printStackTrace();}
        System.out.println("gc after：" + weakReference.get() + "\t内存够用");
    }

    private static void softReference() {
        SoftReference<MyObject> softReference = new SoftReference<>(new MyObject());
        System.out.println("gc before：" + softReference.get());
        System.gc();
        try { TimeUnit.MILLISECONDS.sleep(1000); } catch (InterruptedException e) { e.printStackTrace();}
        System.out.println("gc after：" + softReference.get() + "\t内存够用");

        try {
            byte[] bytes = new byte[20 * 1024 * 1024];
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("gc after：" + softReference.get() + "\t内存不够用");
        }
    }

    private static void strongReference() {
        MyObject myObject = new MyObject();
        System.out.println("gc before：" + myObject);
        myObject = null;
        System.gc();

        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("gc after：" + myObject);
    }
}

class MyObject {
    // 一般开发中不用调用这个方法，本次只是为了讲课演示
    @Override
    // 当垃圾收集确定不再有对该对象的引用时，垃圾收集器在对象上调用该对象
    protected void finalize() throws Throwable {
        System.out.println(Thread.currentThread().getName() + "\t" + "---finalize method invoked....");
    }
}
